feat(cli, webui): add follow-up suggestions feature - #2525
Conversation
📋 Review SummaryThis PR implements a context-aware follow-up suggestions feature similar to Claude Code's NES functionality, suggesting relevant next actions after task completion. The implementation spans core, CLI, and webui packages with a well-structured architecture. Overall, the code is clean and follows project conventions, but there are several issues that should be addressed before merging. 🔍 General Feedback
🎯 Specific Feedback🔴 Critical
🟡 High
🟢 Medium
🔵 Low
✅ Highlights
|
aa3e3fc to
0300da2
Compare
0300da2 to
53cc80d
Compare
Implement context-aware follow-up suggestions that appear after task completion, suggesting relevant next actions like "commit this", "run tests", etc. - Add `followup/` module with types, generator, and rule-based provider - Export follow-up types and functions from core index - 8 default suggestion rules covering common workflows - Add `useFollowupSuggestionsCLI` hook for Ink/React - Integrate suggestion generation in AppContainer when streaming completes - Add Tab key to accept, arrow keys to cycle through suggestions - Display suggestions as ghost text in input prompt - Add `useFollowupSuggestions` hook for React - Update InputForm to display suggestions as placeholder - Add CSS styling for suggestion appearance with counter - Add keyboard handlers (Tab, arrow keys) - After streaming completes with tool calls, suggestions appear - Tab accepts the current suggestion - Left/Right arrows cycle through multiple suggestions - Typing or pasting dismisses the suggestion - Shell command rules (tests, git, npm install) don't work yet due to history not storing tool arguments - VSCode extension integration pending - Web UI needs parent app integration for suggestion generation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Rebased on upstream main (5d02260) - Fixed JSX structure in InputPrompt.tsx - Changed `return;` to `return true;` in follow-up handlers - Added @agentclientprotocol/sdk to core package dependencies - Restored correct BaseTextInput usage (self-closing, no children) - Follow-up suggestions now shown via placeholder prop only Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The types are imported in fileSystemService.ts but the package should not be a runtime dependency of core. It's provided by the CLI package which depends on core. This was causing package-lock.json sync issues on Node.js 24.x CI. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
0762082 to
b1e29a1
Compare
CI Test Failures - Pre-existing IssueThe test failures are caused by a pre-existing flaky test that also fails on upstream/main: Test: Error: Verification: I ran the same test on upstream/main (commit fbf5ed5) and it fails with the identical error. This test failure is NOT caused by the follow-up suggestions feature changes. Files changed by this PR:
None of these files touch the ACP connection code or tests. Suggested actions:
|
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
- Export followupState.ts from core index (was dead code) - Refactor CLI and WebUI hooks to use shared followupReducers (eliminate duplication) - Move side effects out of setState updaters via queueMicrotask - Fix AppContainer useEffect dependency on unstable historyManager.history reference - Reorder matchesRule to check pattern before condition (cheaper first) - Make RuleBasedProvider collect from all matching rules with dedup and limit - Add missing resetGenerator export for testing - Add explicit implements SuggestionProvider to RuleBasedProvider - Fix unstable followup object in useEffect dependency arrays - Merge duplicate imports to fix eslint import/no-duplicates warnings - Standardize copyright year to 2025 - Add test files for followupState, ruleBasedProvider, suggestionGenerator Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds a new “follow-up suggestions” capability across core, CLI, and Web UI so that after a tool-driven turn completes the user sees context-aware next-step prompts (accept via Tab, cycle via arrows).
Changes:
- Core: Introduces
followup/module (types, state reducers, generator, rule-based provider) and exports it from@qwen-code/qwen-code-core, with unit tests. - CLI: Adds an Ink hook + keybindings and wires suggestion generation on stream completion; threads suggestions through UI state into the prompt placeholder.
- Web UI: Adds a React hook,
InputFormintegration (ghost placeholder + key handling), and CSS styling/counter.
Reviewed changes
Copilot reviewed 19 out of 20 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/webui/src/styles/components.css | Styles ghost follow-up placeholder + hover + counter UI. |
| packages/webui/src/index.ts | Exports the new Web UI hook + follow-up types (and re-exports a core type). |
| packages/webui/src/hooks/useFollowupSuggestions.ts | Adds Web UI hook managing follow-up suggestion state and accept/cycle/dismiss behaviors. |
| packages/webui/src/components/layout/InputForm.tsx | Adds follow-up props, ghost placeholder display, Tab/Arrow handling, and dismiss-on-type behavior. |
| packages/vscode-ide-companion/src/services/acpConnection.test.ts | Refactors a test to mock connection behavior via ensureConnection. |
| packages/core/src/index.ts | Re-exports follow-up module from core public index. |
| packages/core/src/followup/types.ts | Defines follow-up suggestion and context/provider interfaces. |
| packages/core/src/followup/suggestionGenerator.ts | Implements generator orchestration + singleton helpers + context extraction helper. |
| packages/core/src/followup/suggestionGenerator.test.ts | Adds unit tests for generator behavior and context extraction. |
| packages/core/src/followup/ruleBasedProvider.ts | Implements default rule set + matching/deduping/priority logic. |
| packages/core/src/followup/ruleBasedProvider.test.ts | Adds unit tests for rule matching, merging, deduping, and limits. |
| packages/core/src/followup/index.ts | Barrel export for follow-up module. |
| packages/core/src/followup/followupState.ts | Adds framework-agnostic follow-up state + reducers (shared by CLI/Web). |
| packages/core/src/followup/followupState.test.ts | Adds unit tests for state reducers. |
| packages/cli/src/ui/hooks/useFollowupSuggestions.tsx | Adds CLI hook to manage follow-up suggestion state and interactions. |
| packages/cli/src/ui/contexts/UIStateContext.tsx | Extends UI state to carry follow-up suggestions. |
| packages/cli/src/ui/components/InputPrompt.tsx | Displays suggestions as placeholder + Tab/Arrow key behaviors + dismiss-on-input. |
| packages/cli/src/ui/components/Composer.tsx | Passes follow-up suggestions from UI state into InputPrompt. |
| packages/cli/src/ui/AppContainer.tsx | Generates suggestions on stream completion using history tool groups and stores them in UI state. |
| package-lock.json | Lockfile updates related to local test-utils dependency placement/metadata. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Fix acceptingRef race: set lock synchronously before queueMicrotask - Derive hasError/wasCancelled from actual tool call statuses - Incorporate rule priority into suggestion priority calculation - Clear suggestions immediately when setSuggestions([]) is called - Add !completion.showSuggestions guard to Tab handler - Fix onAcceptFollowup type from (string) => void to () => void - Fix ToolCallInfo.name doc examples to match display names - Scope CSS counter ::after to data-has-suggestion + empty conditions - Reset regex lastIndex before test() for g/y flag safety - Stabilize hook return with useMemo + onAcceptRef pattern - Add @qwen-code/qwen-code-core as webui external + peerDependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When opening the model selection dialog via /model --fast, the currently configured fastModel is pre-selected instead of the main model. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
/model <Tab> now shows --fast as a completion option with description. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 56 out of 57 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Adds enableCacheSharing, enableSpeculation, and fastModel to the generated JSON schema so CI validation passes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 56 out of 57 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add "Fast Model" to expected labels in systemInfoFields and bugCommand tests to match the new field added to /about and bug report output. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 56 out of 57 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 59 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- modelCommand: use getPersistScopeForModelSelection for fastModel, return meaningful info message instead of empty content - ModelDialog: handle $runtime|authType|modelId format in fast-model mode - forkedQuery: return structuredClone from getCacheSafeParams - client: fix stale comment about history truncation order - speculation: detect abort in .then() handler, set 'aborted' status and cleanup overlay to prevent leaks - docs: update test count table Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 58 out of 59 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- New feature page: followup-suggestions.md covering usage, keybindings, fast model configuration, settings, and quality filters - commands.md: add /model --fast command reference - settings.md: add enableFollowupSuggestions, enableCacheSharing, enableSpeculation, and fastModel settings documentation - _meta.ts: register new page in navigation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 62 out of 63 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- followup-suggestions.md: add 300ms delay, WebUI support, plan mode guard, non-interactive guard, slash commands as single-word, meta/error filters, character limit - settings.md: move fastModel next to model section, add /model --fast cross-reference and link to feature page - overview.md: add followup suggestions to feature list - i18n: add missing translations for 'Set fast model for background tasks' and 'Fast model updated.' in all 6 locales Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 64 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- modelCommand: remove duplicate info message (keep addItem only) - followup-suggestions.md: clarify WebUI requires host app wiring - speculation-design.md: fix abort telemetry description - i18n: add missing translations for fast model strings Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 64 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Use return message instead of addItem + empty return to avoid blank INFO line in history. Also handle missing settings service. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 64 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The /model --fast command now returns the model name directly instead of using this string. Remove dead translations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 64 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Forked queries inherit the main conversation's generationConfig which may have thinkingConfig enabled. This wastes tokens and adds latency for background tasks that don't need reasoning. Explicitly set thinkingConfig.includeThoughts=false in both paths: - createForkedChat (covers forked query + speculation) - generateViaBaseLlm (non-cache-sharing fallback) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- User docs: note that thinking is auto-disabled for suggestions/speculation - Design docs: detail thinkingConfig override in both forked query and BaseLlm paths, explain why cache hits are unaffected Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 63 out of 64 changed files in this pull request and generated no new comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Summary
Implement context-aware follow-up suggestions that appear after task completion, suggesting relevant next actions like "commit this", "run tests", etc.
This feature is similar to Claude Code's NES (Next-Step Suggestions) functionality.
Changes
Core Module (
packages/core)followup/module with:types.ts- TypeScript interfaces for suggestionssuggestionGenerator.ts- Main service orchestrating providersruleBasedProvider.ts- Pattern-based suggestion rulesCLI (
packages/cli)useFollowupSuggestionsCLIhook for Ink/React state managementAppContainerwhen streaming completesWeb UI (
packages/webui)useFollowupSuggestionshook for ReactInputFormto display suggestions as styled placeholderUsage
Example Suggestions
Known Limitations
Test plan
🤖 Generated with Claude Code